/****************************************
 * 2018 - 2021 版权所有 CopyRight(c) 快程乐码信息科技有限公司所有, 未经授权，不得复制、转发
 */

package com.kclm.security03.config.security.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.kclm.security03.config.security.dto.SecurityUser;
import com.kclm.security03.modules.system.entity.Role;
import com.kclm.security03.modules.system.entity.User;
import com.kclm.security03.modules.system.entity.UserRole;
import com.kclm.security03.modules.system.mapper.RoleMapper;
import com.kclm.security03.modules.system.mapper.UserMapper;
import com.kclm.security03.modules.system.mapper.UserRoleMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.LinkedList;
import java.util.List;

/******************
 * @Author yejf
 * @Version v1.0
 * @Create 2020-07-26 22:44
 * @Description TODO
 */
@Service("userDetailsService")
@Slf4j
public class UserDetailsServiceImpl implements UserDetailsService {

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private UserRoleMapper userRoleMapper;

    @Autowired
    private RoleMapper roleMapper;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        //从数据库中取出用户信息
        final List<User> users = this.userMapper.selectList(
                new QueryWrapper<User>().eq("username", username)
        );
        User user = null;
        //判断用户是否存在
        if(!CollectionUtils.isEmpty(users)) {
            //获取用对象
            user = users.get(0);
        } else {
            //抛出异常
            throw new UsernameNotFoundException("用户名不存在!");
        }
        //返回我们封装的SecurityUser对象，并且以 user和List<Role> 做为参数传入
        return new SecurityUser(user, getUserRoles(user.getId()));
    }

    /*******************
     * 根据用户的token 来获取用户信息和角色信息
     * @param token
     * @return
     */
    public SecurityUser getUserByToken(String token) {
        //根据token来查询用户信息
        final List<User> users = this.userMapper.selectList(
                new QueryWrapper<User>().eq("token", token)
        );
        //
        User user = null;
        if(!CollectionUtils.isEmpty(users)) {
            user = users.get(0);
        }
        //再根据用户和角色来封装 SecurityUser
        return user != null ? new SecurityUser(user, getUserRoles(user.getId())) : null;
    }

    /**********************
     * 根据用户的ID来获取此用户拥有的所有角色
     * @param userId
     * @return 用户所拥有的角色
     */
    private List<Role> getUserRoles(Integer userId) {
        //根据userRoleMapper接口来查询，以列 user_id 为条件，查询出所有的roleId信息
        final List<UserRole> userRoles = this.userRoleMapper.selectList(
                new QueryWrapper<UserRole>().eq("user_id", userId)
        );
        //
        List<Role> roleList = new LinkedList<>();
        if(!CollectionUtils.isEmpty(userRoles)) {
            //迭代
            for(UserRole userRole : userRoles) {
                //根据roleid 来查询角色信息
                final Role role = this.roleMapper.selectById(userRole.getRoleId());
                //
                log.debug("添加角色["+role.getCode()+"] 进入集合中");
                roleList.add(role);
            }
        } else {
            log.warn("此用户没有分配任何角色");
        }
        //
        return roleList;
    }

}
